"""
质量评分权重配置管理器
"""
import json
import logging
from typing import Dict, Optional, Any
from datetime import datetime, timedelta
import redis.asyncio as redis

from ..models.quality import QualityDimension, ScenarioType

logger = logging.getLogger(__name__)


class WeightConfigManager:
    """权重配置管理器"""
    
    # 默认权重配置
    DEFAULT_WEIGHTS = {
        ScenarioType.NEWS.value: {
            QualityDimension.ORIGINALITY.value: 0.15,
            QualityDimension.READABILITY.value: 0.20,
            QualityDimension.INFORMATION_DENSITY.value: 0.30,
            QualityDimension.EMOTIONAL_RESONANCE.value: 0.10,
            QualityDimension.STRUCTURE_INTEGRITY.value: 0.25
        },
        ScenarioType.BLOG.value: {
            QualityDimension.ORIGINALITY.value: 0.25,
            QualityDimension.READABILITY.value: 0.25,
            QualityDimension.INFORMATION_DENSITY.value: 0.15,
            QualityDimension.EMOTIONAL_RESONANCE.value: 0.20,
            QualityDimension.STRUCTURE_INTEGRITY.value: 0.15
        },
        ScenarioType.TECHNICAL.value: {
            QualityDimension.ORIGINALITY.value: 0.20,
            QualityDimension.READABILITY.value: 0.15,
            QualityDimension.INFORMATION_DENSITY.value: 0.35,
            QualityDimension.EMOTIONAL_RESONANCE.value: 0.05,
            QualityDimension.STRUCTURE_INTEGRITY.value: 0.25
        },
        ScenarioType.CREATIVE.value: {
            QualityDimension.ORIGINALITY.value: 0.35,
            QualityDimension.READABILITY.value: 0.20,
            QualityDimension.INFORMATION_DENSITY.value: 0.10,
            QualityDimension.EMOTIONAL_RESONANCE.value: 0.25,
            QualityDimension.STRUCTURE_INTEGRITY.value: 0.10
        },
        ScenarioType.GENERAL.value: {
            QualityDimension.ORIGINALITY.value: 0.20,
            QualityDimension.READABILITY.value: 0.20,
            QualityDimension.INFORMATION_DENSITY.value: 0.20,
            QualityDimension.EMOTIONAL_RESONANCE.value: 0.20,
            QualityDimension.STRUCTURE_INTEGRITY.value: 0.20
        }
    }
    
    def __init__(self, redis_client: Optional[redis.Redis] = None):
        """
        初始化权重配置管理器
        
        Args:
            redis_client: Redis客户端（可选）
        """
        self.redis_client = redis_client
        self.cache_prefix = "quality:weights:"
        self.cache_ttl = 300  # 5分钟缓存
    
    async def get_weights(
        self, 
        scenario: ScenarioType,
        use_cache: bool = True
    ) -> Dict[str, float]:
        """
        获取权重配置
        
        Args:
            scenario: 场景类型
            use_cache: 是否使用缓存
            
        Returns:
            权重配置字典
        """
        cache_key = f"{self.cache_prefix}{scenario.value}"
        
        # 尝试从缓存获取
        if use_cache and self.redis_client:
            try:
                cached = await self.redis_client.get(cache_key)
                if cached:
                    weights = json.loads(cached)
                    logger.debug(f"Loaded weights from cache for scenario: {scenario.value}")
                    return weights
            except Exception as e:
                logger.warning(f"Failed to get weights from cache: {e}")
        
        # 从配置获取
        weights = self.DEFAULT_WEIGHTS.get(
            scenario.value,
            self.DEFAULT_WEIGHTS[ScenarioType.GENERAL.value]
        )
        
        # 存入缓存
        if use_cache and self.redis_client:
            try:
                await self.redis_client.setex(
                    cache_key,
                    self.cache_ttl,
                    json.dumps(weights)
                )
                logger.debug(f"Cached weights for scenario: {scenario.value}")
            except Exception as e:
                logger.warning(f"Failed to cache weights: {e}")
        
        return weights
    
    async def set_weights(
        self,
        scenario: ScenarioType,
        weights: Dict[str, float],
        validate: bool = True
    ) -> bool:
        """
        设置权重配置
        
        Args:
            scenario: 场景类型
            weights: 权重配置
            validate: 是否验证权重
            
        Returns:
            是否设置成功
        """
        if validate:
            if not self.validate_weights(weights):
                return False
        
        cache_key = f"{self.cache_prefix}{scenario.value}"
        
        # 更新内存配置
        self.DEFAULT_WEIGHTS[scenario.value] = weights
        
        # 更新缓存
        if self.redis_client:
            try:
                await self.redis_client.setex(
                    cache_key,
                    self.cache_ttl,
                    json.dumps(weights)
                )
                
                # 记录更新历史
                history_key = f"{self.cache_prefix}history:{scenario.value}"
                history_entry = {
                    'weights': weights,
                    'updated_at': datetime.utcnow().isoformat(),
                    'scenario': scenario.value
                }
                await self.redis_client.lpush(
                    history_key,
                    json.dumps(history_entry)
                )
                # 只保留最近100条历史
                await self.redis_client.ltrim(history_key, 0, 99)
                
                logger.info(f"Updated weights for scenario: {scenario.value}")
                return True
            except Exception as e:
                logger.error(f"Failed to update weights: {e}")
                return False
        
        return True
    
    def validate_weights(self, weights: Dict[str, float]) -> bool:
        """
        验证权重配置
        
        Args:
            weights: 权重配置
            
        Returns:
            是否有效
        """
        # 检查所有维度是否存在
        required_dims = set(dim.value for dim in QualityDimension)
        provided_dims = set(weights.keys())
        
        if required_dims != provided_dims:
            missing = required_dims - provided_dims
            extra = provided_dims - required_dims
            if missing:
                logger.error(f"Missing dimensions: {missing}")
            if extra:
                logger.error(f"Extra dimensions: {extra}")
            return False
        
        # 检查权重值范围
        for dim, weight in weights.items():
            if not 0 <= weight <= 1:
                logger.error(f"Weight for {dim} out of range: {weight}")
                return False
        
        # 检查权重总和
        total = sum(weights.values())
        if abs(total - 1.0) > 0.01:  # 允许小误差
            logger.error(f"Weights sum to {total}, should be 1.0")
            return False
        
        return True
    
    async def get_weight_history(
        self,
        scenario: ScenarioType,
        limit: int = 10
    ) -> list:
        """
        获取权重配置历史
        
        Args:
            scenario: 场景类型
            limit: 返回记录数
            
        Returns:
            历史记录列表
        """
        if self.redis_client is None:
            return []
        
        history_key = f"{self.cache_prefix}history:{scenario.value}"
        
        try:
            history = await self.redis_client.lrange(history_key, 0, limit - 1)
            return [json.loads(entry) for entry in history]
        except Exception as e:
            logger.error(f"Failed to get weight history: {e}")
            return []
    
    async def reset_weights(self, scenario: ScenarioType) -> bool:
        """
        重置为默认权重
        
        Args:
            scenario: 场景类型
            
        Returns:
            是否重置成功
        """
        default_weights = self.get_default_weights(scenario)
        return await self.set_weights(scenario, default_weights, validate=False)
    
    def get_default_weights(self, scenario: ScenarioType) -> Dict[str, float]:
        """
        获取默认权重配置
        
        Args:
            scenario: 场景类型
            
        Returns:
            默认权重配置
        """
        # 返回类定义的默认配置
        defaults = {
            ScenarioType.NEWS: {
                QualityDimension.ORIGINALITY.value: 0.15,
                QualityDimension.READABILITY.value: 0.20,
                QualityDimension.INFORMATION_DENSITY.value: 0.30,
                QualityDimension.EMOTIONAL_RESONANCE.value: 0.10,
                QualityDimension.STRUCTURE_INTEGRITY.value: 0.25
            },
            ScenarioType.BLOG: {
                QualityDimension.ORIGINALITY.value: 0.25,
                QualityDimension.READABILITY.value: 0.25,
                QualityDimension.INFORMATION_DENSITY.value: 0.15,
                QualityDimension.EMOTIONAL_RESONANCE.value: 0.20,
                QualityDimension.STRUCTURE_INTEGRITY.value: 0.15
            },
            ScenarioType.TECHNICAL: {
                QualityDimension.ORIGINALITY.value: 0.20,
                QualityDimension.READABILITY.value: 0.15,
                QualityDimension.INFORMATION_DENSITY.value: 0.35,
                QualityDimension.EMOTIONAL_RESONANCE.value: 0.05,
                QualityDimension.STRUCTURE_INTEGRITY.value: 0.25
            },
            ScenarioType.CREATIVE: {
                QualityDimension.ORIGINALITY.value: 0.35,
                QualityDimension.READABILITY.value: 0.20,
                QualityDimension.INFORMATION_DENSITY.value: 0.10,
                QualityDimension.EMOTIONAL_RESONANCE.value: 0.25,
                QualityDimension.STRUCTURE_INTEGRITY.value: 0.10
            },
            ScenarioType.GENERAL: {
                QualityDimension.ORIGINALITY.value: 0.20,
                QualityDimension.READABILITY.value: 0.20,
                QualityDimension.INFORMATION_DENSITY.value: 0.20,
                QualityDimension.EMOTIONAL_RESONANCE.value: 0.20,
                QualityDimension.STRUCTURE_INTEGRITY.value: 0.20
            }
        }
        
        return defaults.get(scenario, defaults[ScenarioType.GENERAL])
    
    async def optimize_weights(
        self,
        scenario: ScenarioType,
        performance_data: Dict[str, Any]
    ) -> Dict[str, float]:
        """
        基于性能数据优化权重（预留接口）
        
        Args:
            scenario: 场景类型
            performance_data: 性能数据
            
        Returns:
            优化后的权重
        """
        # 预留接口，未来可以基于机器学习模型优化权重
        logger.info(f"Weight optimization for {scenario.value} - Feature reserved for future")
        
        # 暂时返回当前权重
        return await self.get_weights(scenario)
    
    async def export_config(self) -> Dict[str, Any]:
        """
        导出所有权重配置
        
        Returns:
            完整配置字典
        """
        config = {
            'version': '1.0.0',
            'exported_at': datetime.utcnow().isoformat(),
            'scenarios': {}
        }
        
        for scenario in ScenarioType:
            weights = await self.get_weights(scenario, use_cache=False)
            config['scenarios'][scenario.value] = {
                'weights': weights,
                'description': self.get_scenario_description(scenario)
            }
        
        return config
    
    def get_scenario_description(self, scenario: ScenarioType) -> str:
        """
        获取场景描述
        
        Args:
            scenario: 场景类型
            
        Returns:
            场景描述
        """
        descriptions = {
            ScenarioType.NEWS: "新闻类内容，注重信息量和结构",
            ScenarioType.BLOG: "博客类内容，平衡原创性和可读性",
            ScenarioType.TECHNICAL: "技术文档，强调信息密度和结构",
            ScenarioType.CREATIVE: "创意写作，重视原创性和情感",
            ScenarioType.GENERAL: "通用内容，各维度均衡"
        }
        
        return descriptions.get(scenario, "通用场景")